package com.stu.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;

@Data
@AllArgsConstructor
@Slf4j
//这个AliOssUtil类是一个工具类，它封装了与阿里云对象存储服务（OSS）交互的一些基本操作。这个类的主要功能是上传文件到OSS，并返回文件的访问URL。
public class AliOssUtil {

    private String endpoint;//阿里云OSS服务的访问点，通常是OSS服务的URL。
    private String accessKeyId;//阿里云账号的AccessKeyId，用于身份验证。
    private String accessKeySecret;//阿里云账号的AccessKeySecret，用于身份验证。
    private String bucketName;//要操作的OSS存储桶（Bucket）的名称。
    /**
     * 文件上传
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {//bytes（要上传的文件的字节数组）和objectName（在OSS中存储的文件名）
        // 创建OSSClient实例。 该实例是阿里云OSS Java SDK中用于与OSS交互的客户端。
        // ossClient：这是OSSClient的一个实例，代表一个与阿里云OSS服务的连接客户端。
        // 通过这个客户端，你可以执行各种OSS操作，比如上传、下载、删除文件等。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            //这行代码的作用就是将bytes数组中的内容作为文件上传到OSS的指定存储桶（bucketName）中，并给这个文件指定一个键（objectName）。
            // 上传成功后，你就可以通过OSS提供的URL来访问这个文件了。

            //putObject：这是OSSClient类中的一个方法，用于上传一个对象（在这里指的是文件）到OSS
            //bucketName：这是你要上传文件到的OSS存储桶的名称。存储桶是OSS中用于存储对象的逻辑空间，你可以把它想象成一个文件夹或者一个目录。
            //objectName：这是你要上传的文件在OSS中的名称。
            //      --在OSS中，每个对象都有一个唯一的键（Key），这里的objectName就是这个键。通过这个键，你可以唯一地定位到OSS中的某个文件。

            //new ByteArrayInputStream(bytes)：这是一个ByteArrayInputStream的实例，它接收一个字节数组bytes作为参数。
            //      --ByteArrayInputStream是Java中的一个类，它允许你将字节数组作为输入流来使用。
            //      --这里，它被用来将bytes数组作为文件内容传递给putObject方法。

            // 创建PutObject请求。 使用ossClient.putObject方法将文件内容上传到指定的OSS存储桶（Bucket）中。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        }
        //如果上传过程中发生异常，代码会捕获OSSException（与OSS服务相关的异常）和ClientException（客户端异常），并打印异常信息。
        catch (OSSException oe) {//制定OSSException异常信息
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {//制定ClientException异常信息
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {//在finally块中，无论是否发生异常，都会关闭ossClient，释放资源。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }
}
